from flask_restful import Resource
from comment.models.user import User
from flask import current_app,request,g
from comment.utils.aliyun_sms_send import send_sms
import random
import json
from comment.utils.limiter import limiter as lmt
from . import constants
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser
from comment.utils import parser
from comment.models import db
from comment.utils.tokens_pyjwt import generate_tokens
from comment.utils.decorators import login_required

#我们定义的测试的资源类
class Shopping_User(Resource):
    #在get方法上加拦截，属性名字固定,可以添加多个装饰器
    method_decorators = {
        'get':[login_required],
        'post':[login_required]
    }

    def get(self):
        #输出日志要指定输出级别，如果是debug级别就写current_app.logger.debug('我的测试日志')
        #‘我的测试日志’是日志输出内容，显示在%(message)s这个里面
        current_app.logger.info('我的测试日志')
        #这里的代码可能会用到User模型类
        return {'hello':'world'}

    def post(self):
        return {'post':'post'}

    def put(self):
        return {'put':'put'}
class User_SMS(Resource):
    error_message='too many requests.'
    # 可以写多个限制器
    decorators = [
        #限制可以写三个参数；参数1：限流的速率,参数2：key_func(它接收的参数是函数)
        #参数3：超出限制后的提示信息
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                  key_func=lambda:request.args['phone'],
                  error_message=error_message),
        lmt.limit(constants.LIMIT_SMS_CODE_BY_IP,
                  key_func=get_remote_address,
                  error_message=error_message)
    ]

    #发送验证码短信
    def get(self):
        phone = request.args.get('phone').strip()
        code = random.randint(1000,9999)
        result = send_sms(phone,str(code)) #返回的是json格式的字符串
        result = json.loads(result) #把json变成字典
        #result 往里面添加手机号码
        result['phone']=phone

        #短信验证码发送成功之后，还需要把验证码存放到redis数据库中以便于下次验证
        #验证码时效为5分钟,setex参数1位key，参数2为时效时间，参数3为值
        redis_client.setex('shopping:code:{}'.format(phone),constants.SMS_CODE_EXPIRES,code)

        return result

class AuthorizationCodeResource(Resource):

    '''
    提交手机号和验证码，开始验证
    '''

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone',type=parser.mobile,required=True)
        rp.add_argument('code',type=parser.regex(r'^\d{4}$'),required=True)
        args = rp.parse_args()
        phone = args.phone
        code = args.code

        #从redis数据库中得到之前保存的验证码
        key = 'shopping:code:{}'.format(phone)
        try:
            real_code = redis_client.get(key) #从redis中返回的是字节数据
        except ConnectionError as e:
            current_app.logger.error(e)
            return {'message':'redis db connect error.'},400
        #开始校验(数字的话无论什么编码格式如utf-8或者gbk都没关系所以不用加编码格式)
        if not real_code or real_code.decode() != code:
            return {'message':'Invalid code.'},400
        #校验成功
        return {'phone':phone,'msg':'code success.'}

class RegisterUserResource(Resource):
    '''
    填写账户信息，完成用户注册
    '''
    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', type=parser.mobile, required=True)
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        rp.add_argument('email', type=parser.email, required=True)
        args = rp.parse_args()
        phone = args.phone
        username = args.username
        password = args.password
        email = args.email

        #验证用户名是否唯一：先从mysql数据库中根据当前用户名查询
        u = User.query.filter(User.username == username).first()
        if u:#用户名已经存在
            current_app.logger.info('{}：用户名已经存在，请换一个'.format(username))
            return {'message':'The username is already exists.'},400

        #把用户信息保存到数据库中
        u = User(username=username,pwd=password,email=email,status=0)
        db.session.add(u)
        db.session.commit()
        return {'msg': 'OK'}

class UserLoginResource(Resource):
    """
    登录
    """
    def post(self):
        username = request.form.get('username')
        password = request.form.get('password')
        if not all([username, password]):
            return {'message': '数据不完整'}, 401
        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(password):
                #必须通过登录成功后的用户id得到token，然后把token返回给前端
                token = generate_tokens(user.id)
                return {'msg': 'Login Success.','token':token,'username':username}
        return {'message': '用户名或密码错误'}, 400

class UserLoginOutResource(Resource):
    """
    退出登录
    """
    def post(self):
        if g.user_id:
            g.user_id =None
        return {'msg':'退出登录'}

class IsExistPhoneResource(Resource):
    """
    判断手机号是否存在
    """
    def post(self):
        phone=request.form.get('phone')
        user=User.query.filter(User.phone == phone).first()
        if user:# 如果用户有，表示手机号存在
            return {'isExist':True,'message':'此手机号码已经注册','code':203}
        return {'msg':'手机号可以注册'}

